package com.cskaoyan.javase.oop3._1interface._0introduction;

/**
 * 现在我们有了新需求：一部分猫和狗，经过了特殊训练，能够直立行走了。
 * 那么这群特殊的猫和狗，怎么描述它们呢？
 *
 * 所以肯定需要定义一个新的类。比如叫SuperCat、SuperDog，然后继承Cat和Dog，最后再去新增一个直立行走的方法
 *
 * 定义抽象类然后让SuperCat去实现抽象方法,这种想法是好的,实现不了,因为java不支持多继承.
 * 这时抽象类就达不到需求了,并且:
 * 1.抽象类应该作为顶层父类使用,这里不是顶层父类.甚至它就不该是一个类.因为它只描述行为的抽象
 * 2.继承需要考虑"is-a"关系,这里完全没有.
 *
 * 总之,一个类是达不到需求了,就需要一个新的数据类型:
 * 1.这个数据类型,被继承不受单继承限制
 * 2.它不是对属性和行为的抽象,而是只关注行为的抽象
 * 3.它也不是继承的"is-a"关系
 *
 * 这种新的数据类型就是接口,它是一种和class同等级别的数据类型,是一种引用数据类型
 *
 * 定义接口的语法:
 * [访问权限修饰] interface 接口名{
 *     // 接口体
 * }
 * 访问权限修饰符和class一样,也是两种
 * 接口名和类名一样,大驼峰式的书写格式.而且有些程序员喜欢一些独特的命名方式,可以在接口名前加大写字母"I",表示它是一个接口(这不是强制的,不这么命名的接口多了去)
 *
 * 接口不注重属性的抽象,更关注方法,而且接口中可以定义抽象方法.
 *
 * 接口的继承,接口不是类,所以接口的继承用自己的关键字"implements",所以接口的继承叫做"实现"
 * 当然实现接口的本质,仍然是继承接口,接口可以称之为"父接口",实现接口的类也可以称之为接口的"子类"
 *
 * 接口不受单继承限制,而且一个类可以实现多个接口
 * 那么多个接口,就会成为该类的"父接口"(父类)
 *
 * @since 11:10
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 思考: SuperDog可以有几种方式创建对象
        SuperDog sd = new SuperDog();
        Dog d = new SuperDog();
        ISpecialSkills iss = new SuperDog();
        iss.walkUpright();
        ((SuperDog) iss).shout();
        iss = new SuperCat();
        iss.walkUpright();

        IA ia = new SuperDog();
        ((SuperDog) ia).walkUpright();
        ((SuperDog) ia).shout();
    }
}

abstract class Animal {
    public abstract void shout();
}

class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("猫叫");
    }

}

class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}

class SuperCat extends Cat implements ISpecialSkills {
    // 可以直立行走
    public void walkUpright() {
        System.out.println("超级猫可以直立行走");
    }
}

class SuperDog extends Dog implements ISpecialSkills, IA {
    // 可以直立行走
    public void walkUpright() {
        System.out.println("超级狗可以直立行走");
    }
}

// 抽取出抽象方法,写进抽象类
abstract class SpecialSkills {
    public abstract void walkUpright();
}

// Modifier 'abstract' is redundant for interfaces
abstract interface ISpecialSkills {
    public abstract void walkUpright();
}

interface IA {
}